#include "accountmember.h"
#include "icon/iconmanager.h"
#include "network/networkmanager.h"

#include "network/networkhttprequest.h"
#include "network/networkresponse.h"

#include "request/getavatarrequest.h"
#include "network/image/imagegetimageresponse.h"

#include "request/getprofilerequest.h"
#include "response/getprofileresponse.h"

#include "profile/updateprofilerequest.h"
#include "profile/updateprofileresponse.h"

#include "request/postmessagestatusrequest.h"
#include "response/postmessagestatusresponse.h"


#include <QDebug>


using namespace Account;

Member::Member(qint64 id, QObject *parent)
    : QObject(parent)
    , m_onlineStatus(false)
    , m_isProfileEmpty(true)
{
    setId(id);

    init();
    setConnection();
}


Member::Member(qint64 id,
               const QString &fullName,
               const QString &displayName,
               const QString &avatar,
               QObject *parent)
    : QObject(parent)
    , m_onlineStatus(false)
    , m_isProfileEmpty(false)
{
    setId(id);
    setAvatarUrl(avatar);
    setFullName(fullName);
    setDisplayName(displayName);

    init();
    setConnection();
}


Member::Member(const Profile::ProfileData &profile, QObject *parent)
    : QObject(parent)
    , m_onlineStatus(false)
    , m_isProfileEmpty(false)
{
    m_profile = profile;

    init();
    setConnection();
}


bool Member::operator < (const Member &another) const
{
    return (displayName() < another.displayName());
}


bool Member::compare(const Member *first, const Member *second)
{
    if ((first != NULL) && (second != NULL)) {
        return (*first < *second);
    }

    return true;
}


void Member::init()
{
    m_image = QImage(":/default/defaultavatar/Image/Theme/Default/DefaultAvatar/avatar50x50.png");
}


void Member::setConnection() const
{
    connect(this, &Member::profileGotten,
            this, &Member::onProfileGotten);
}


void Member::setId(qint64 id)
{
    m_profile.setMemberId(id);
}


qint64 Member::id() const
{
    return m_profile.memberId();
}


void Member::setFullName(const QString &text)
{
    m_profile.setFullName(text);
}


const QString &Member::fullName() const
{
    return m_profile.fullName();
}


void Member::setDisplayName(const QString &text)
{
    m_profile.setDisplayName(text);
}


const QString &Member::displayName() const
{
    return m_profile.displayName();
}


void Member::setAvatarUrl(const QString &url)
{
    m_profile.setAvatarUrl(url);
    emit avatarUrlChanged(this);
}


void Member::setMessageStatus(const QString &text)
{
    m_profile.setMessageStatus(text);
}


void Member::setOnlineStatus(bool status)
{
    m_onlineStatus = status;
    emit onlineStatusSet(this);
}


bool Member::onlineStatus() const
{
    return m_onlineStatus;
}


QPixmap Member::pixmap() const
{
    return QPixmap::fromImage(m_image);
}


const QImage &Member::image() const
{
    return m_image;
}


void Member::setImage(const QImage &image)
{
    m_image = image;
}


void Member::setProfile(const Profile::ProfileData &profile)
{
    m_profile = profile;
    setIsProfileEmpty(false);
    emit profileSet(this);
}


const Profile::ProfileData &Member::profile() const
{
    return m_profile;
}


void Member::setIsProfileEmpty(bool value)
{
    m_isProfileEmpty = value;
}


bool Member::isProfileEmpty() const
{
    return m_isProfileEmpty;
}


void Member::updateProfile(const Profile::ProfileData &profile)
{
    emit profileAboutToBeUpdated(this);
    m_profile = profile;
    emit profileUpdated(this);
    emit dataChanged(this);
}


void Member::changeFullName(const QString &text)
{
    if (m_profile.fullName() == text)
        return;

    m_profile.setFullName(text);
    emit fullNameChanged(this);
    emit dataChanged(this);
}


void Member::changeDisplayName(const QString &text)
{
    if (m_profile.displayName() == text)
        return;

    m_profile.setDisplayName(text);
    emit displayNameChanged(this);
    emit dataChanged(this);
}


void Member::changeFirstName(const QString &text)
{
    if (m_profile.firstName() == text)
        return;

    m_profile.setFirstName(text);
    emit firstNameChanged(this);
    emit dataChanged(this);
}


void Member::changeLastName(const QString &text)
{
    if (m_profile.lastName() == text)
        return;

    m_profile.setLastName(text);
    emit lastNameChanged(this);
    emit dataChanged(this);
}


void Member::updateImage(const QImage &image)
{
    emit avatarImageAboutToBeChanged(this);
    m_image = image;
    emit avatarImageChanged(this);
    emit dataChanged(this);
}


void Member::updateMessageStatus(const QString &text)
{
    if (m_profile.messageStatus() == text)
        return;

    m_profile.setMessageStatus(text);
    emit messageStatusChanged(this);
    emit dataChanged(this);
}


void Member::changeBirthday(const QString &text)
{
    if (m_profile.birthday() == text)
        return;

    m_profile.setBirthday(text);
    emit birthdayChanged(this);
    emit dataChanged(this);
}


void Member::changeEmail(const QString &text)
{
    if (m_profile.email() == text)
        return;

    m_profile.setEmail(text);
    emit emailChanged(this);
    emit dataChanged(this);
}


void Member::changeOnlineStatus(bool status)
{
    m_onlineStatus = status;
    emit onlineStatusUpdated(this);
    emit dataChanged(this);
}


void Member::changeYahooId(const QString &text)
{
    if (m_profile.yahooId() == text)
        return;

    m_profile.setYahooId(text);
    emit yahooIdChanged(this);
    emit dataChanged(this);
}


void Member::changeGoogleId(const QString &text)
{
    if (m_profile.googleId() == text)
        return;

    m_profile.setGoogleId(text);
    emit googleIdChanged(this);
    emit dataChanged(this);
}


void Member::changeAvatarImage(const QImage &image)
{
    m_image = image;
    emit avatarImageChanged(this);
    emit dataChanged(this);
}


void Member::changeAvatarUrl(const QString &text)
{
    if (m_profile.avatarUrl() == text)
        return;

    m_profile.setAvatarUrl(text);
    emit avatarUrlChanged(this);
    emit dataChanged(this);
}


void Member::changeProfileUrl(const QString &text)
{
    if (m_profile.profileUrl() == text)
        return;

    m_profile.setProfileUrl(text);
    emit profileUrlChanged(this);
    emit dataChanged(this);
}


void Member::changeCity(const QString &text)
{
    if (m_profile.city() == text)
        return;

    m_profile.setCity(text);
    emit cityChanged(this);
    emit dataChanged(this);
}


const QString &Member::firstName() const
{
    return m_profile.firstName();
}


const QString &Member::lastName() const
{
    return m_profile.lastName();
}


const QString &Member::birthday() const
{
    return m_profile.birthday();
}


const QString &Member::email() const
{
    return m_profile.email();
}


const QString &Member::messageStatus() const
{
    return m_profile.messageStatus();
}


const QString &Member::avatarUrl() const
{
    return m_profile.avatarUrl();
}


const QString &Member::profileUrl() const
{
    return m_profile.profileUrl();
}


const QString &Member::yahooId() const
{
    return m_profile.yahooId();
}


const QString &Member::googleId() const
{
    return m_profile.googleId();
}


const QString &Member::city() const
{
    return m_profile.city();
}


int Member::gender() const
{
    return m_profile.gender();
}


void Member::startRequestData()
{
    postGetProfileRequest();
}


void Member::postGetAvatarRequest()
{
    if (avatarUrl().isNull() || avatarUrl().isEmpty())
        return;

    GetAvatarRequest *avatarRequest = new GetAvatarRequest(this);
    connect(avatarRequest, &GetAvatarRequest::responded,
            this, &Member::onGetAvatarResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(avatarRequest)) {
        delete avatarRequest;
        avatarRequest = NULL;
        qDebug() << "Can not request GetAvatar with id:" << id();
        return;
    }
}


void Member::postGetMessageStatusRequest()
{
//    QString sessionKey = Network::Manager::instance()->sessionKey();
//    GetMessageStatusRequest *request = new GetMessageStatusRequest(id(),
//                                                                   sessionKey);
//    connect(request,
//            &GetMessageStatusRequest::responded,
//            this,
//            &Member::onGetMessageStatusResponsed);
    
//    Network::Manager *manager = Network::Manager::instance();
//    if (!manager->post(request)) {
//        delete request;
//        request = NULL;
//        qDebug() << "Can not request GetMessageStatus with id:" << id();
//        return;
//    }
}


void Member::postPostMessageStatusRequest(const QString &messageStatus)
{
    QString sessionKey = Network::Manager::instance()->sessionKey();
    PostMessageStatusRequest *request =
            new PostMessageStatusRequest(messageStatus, sessionKey);
    connect(request,
            &PostMessageStatusRequest::responded,
            this,
            &Member::onPostMessageStatusResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(request)) {
        delete request;
        request = 0;
        return;
    }

    m_messageStatusTemp = messageStatus;
}


void Member::postPostProfileRequest(const QString &fullName,
                                    const QString &email,
                                    const QString &gender,
                                    const QString &birthday)
{
    QString sessionKey = Network::Manager::instance()->sessionKey();
    Profile::UpdateProfileRequest *postUpdateProfileRequset = new Profile::UpdateProfileRequest(sessionKey);
    postUpdateProfileRequset->setProfile(fullName, email,gender,birthday);
    connect(postUpdateProfileRequset, &Profile::UpdateProfileRequest::responded,
            this, &Member::onPostProfileResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(postUpdateProfileRequset)) {
        delete postUpdateProfileRequset;
        postUpdateProfileRequset = NULL;
        return;
    }
}


void Member::postGetProfileRequest()
{
    //qDebug() << "Member::postGetProfileRequest()";
    QString sessionKey = Network::Manager::instance()->sessionKey();
    GetProfileRequest *getProfileRequest = new GetProfileRequest(id(), sessionKey);
    connect(getProfileRequest, &GetProfileRequest::responded,
            this, &Member::onGetProfileResponsed);

    Network::Manager *manager = Network::Manager::instance();
    if (!manager->post(getProfileRequest)) {
        delete getProfileRequest;
        getProfileRequest = NULL;
        qDebug() << "Can not request profile with id:" << id();
        return;
    }
}


void Member::onGetAvatarResponsed(Network::HttpRequest *request)
{
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();

    const Network::GetImageResponse &avatarResponse = (const Network::GetImageResponse &)response;
    QImage image = avatarResponse.image();
    updateImage(image);

    request->deleteLater();
}


void Member::onGetMessageStatusResponsed(Network::HttpRequest *request)
{
//    const Network::HttpRequest &constRequest = *request;
//    const Network::Response &response = constRequest.response();

//    const GetMessageStatusResponse &messageStatusResponse = \
//            (const GetMessageStatusResponse &)response;

//    QString messageStatus = messageStatusResponse.messageStatus();
//    updateMessageStatus(messageStatus);

//    request->deleteLater();
}


void Member::onPostMessageStatusResponsed(Network::HttpRequest *request)
{
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();

    const PostMessageStatusResponse &postMessageStatusResponse = \
            (const PostMessageStatusResponse &)response;

    if (postMessageStatusResponse.isUpdateSuccess()) {
        QString messageStatus = m_messageStatusTemp;
        updateMessageStatus(messageStatus);
        m_messageStatusTemp.clear();
        emit messageStatusChanged(this);
    }

    request->deleteLater();
}


void Member::onGetProfileResponsed(Network::HttpRequest *request)
{
    //qDebug() <<  "Member::onGetProfileResponsed";
    const Network::HttpRequest &constRequest = *request;
    const Network::Response &response = constRequest.response();


    const GetProfileResponse &profileResponse = \
            (const GetProfileResponse &)response;

    Profile::ProfileData profile = profileResponse.profile();
    profile.setMessageStatus(m_profile.messageStatus());

    if (isProfileEmpty())
        setProfile(profile);
    else
        updateProfile(profile);

    emit profileGotten(this);

    request->deleteLater();
}


void Member::onProfileGotten(Member *)
{
    postGetAvatarRequest();
    postGetMessageStatusRequest();
}


void Member::onProfileSet(Member *)
{
}


void Member::onProfileUpdated(Member *)
{
}


void Member::onPostProfileResponsed(Network::HttpRequest *request)
{
    request->deleteLater();
}
